﻿using Abp.Domain.Repositories;
using Choucius.Boilerplate9.Common;
using Choucius.Boilerplate9.DtoBase;
using Choucius.Boilerplate9.PlasticContainerLogs;
using Choucius.Boilerplate9.PlasticContainers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;

namespace Choucius.Boilerplate9.UR5208
{
    /// <summary>
    /// UR5208 RFID读写器
    /// </summary>
    public class UR5208AppService : IUR5208AppService
    {
        private readonly IRepository<PlasticContainerLog, long> _plasticContainerLogRepository;
        private readonly IRepository<PlasticContainer, Guid> _plasticContainerRepository;

        public UR5208AppService(IRepository<PlasticContainerLog, long> plasticContainerLogRepository, IRepository<PlasticContainer, Guid> plasticContainerRepository)
        {
            _plasticContainerLogRepository = plasticContainerLogRepository;
            _plasticContainerRepository = plasticContainerRepository;
        }

        #region 废弃的方法
        /*
        async Task UR5208ReadAndSaveAsync(string ip, int port)
        {
            //throw new NotImplementedException();
            // 获取最近1分钟内绑定产品的吸塑盒列表
            var exList = _plasticContainerLogRepository.GetAll().Where(x => x.CreationTime >= DateTime.Now.AddMinutes(-1) && x.Status == Enum.LabelStatus.ProductBinding).ToList();
            var list = UR5208Read(ip, port);
            foreach (string item in list)
            {
                bool isExist = false;
                string rfid = RFID.GetRFIDfromEPC(item);
                foreach (var ex in  exList)
                {
                    if (rfid == ex.RFID)
                    {
                        isExist = true;
                        break;
                    }
                }
                if (!isExist)
                {
                    var entity = _plasticContainerRepository.GetAllList().FirstOrDefault(x => x.RFID == rfid);
                    if (entity != null)
                    {
                        entity.Status = LabelStatus.ProductBinding;
                        entity.LastModificationTime = DateTime.Now;
                        entity.LastModifierUserId = 0;
                        await _plasticContainerRepository.UpdateAsync(entity);

                        // 历史记录
                        var newLog = new PlasticContainerLog
                        {
                            RFID = rfid,
                            Status = LabelStatus.ProductBinding,
                            CreationTime = DateTime.Now,
                            CreatorUserId = 0
                        };
                        await _plasticContainerLogRepository.InsertAsync(newLog);
                    }
                }
            }
        }
        */
        #endregion

        public ResponseDto UR5208ReadAndWrite(int workStationId)
        {
            var response = new ResponseDto();
            // 连接UR5208
            string ip = "192.168.4.51"; // RFID读写器的IP地址
            int port = 6000; // RFID读写器的端口号

            byte fComAdr = Convert.ToByte("FF", 16); // $FF;
            int portHandle = 0; // 
            int openReturn = UR5208Basic.OpenNetPort(port, ip, ref fComAdr, ref portHandle);
            if (openReturn == 53) // 53表示已经打开端口
            {
                int closeReturnTemp = UR5208Basic.CloseNetPort(portHandle);
                if (closeReturnTemp != 0)
                {
                    response.Code = openReturn;
                    response.Message = "TCP/IP关闭端口错误";
                    return response;
                }
                openReturn = UR5208Basic.OpenNetPort(port, ip, ref fComAdr, ref portHandle);
            }
            if ((openReturn == 0x35) || (openReturn == 0x30))
            {
                response.Code = openReturn;
                response.Message = "TCP/IP通讯错误";
                return response;
            }
            // 读取数据记录在list
            var list = new List<string>();
            //int i;
            int CardNum = 0;
            int Totallen = 0;
            int EPClen, m;
            byte[] EPC = new byte[5000];
            int CardIndex;
            string temps;
            byte AdrTID = 0;
            byte LenTID = 0;
            byte TIDFlag = 0;
            int readReturn = UR5208Basic.Inventory_G2(ref fComAdr, AdrTID, LenTID, TIDFlag, EPC, ref Totallen, ref CardNum, portHandle);
            if ((readReturn == 1) | (readReturn == 2) | (readReturn == 3) | (readReturn == 4) | (readReturn == 0xFB))//代表已查找结束，
            {
                byte[] daw = new byte[Totallen];
                Array.Copy(EPC, daw, Totallen);
                temps = ByteArrayToHexString(daw);
                m = 0;

                if (CardNum == 0)
                {
                    response.Code = 404;
                    response.Message = "未读取到任何信息。";
                    return response;
                }
                for (CardIndex = 0; CardIndex < CardNum; CardIndex++)
                {
                    EPClen = daw[m];
                    string sEPC = temps.Substring(m * 2 + 2, EPClen * 2);
                    m = m + EPClen + 1;
                    if (sEPC.Length != EPClen * 2)
                        continue;
                    if (!list.Contains(sEPC))
                    {
                        list.Add(sEPC);
                    }
                }
            }
            // TODO：获取当前机台生产产品信息
            string rfid = list.FirstOrDefault();
            rfid = RFID.GetRFIDfromEPC(rfid);

            // 写入数据
            string data = rfid;
            int errorCode = -1;
            byte WriteEPClen = Convert.ToByte(data.Length / 2);
            EPC = HexStringToByteArray(data);
            var fPassWord = HexStringToByteArray("00000000"); // 默认密码
            int writeReturn = UR5208Basic.WriteEPC_G2(ref fComAdr, fPassWord, EPC, WriteEPClen, ref errorCode, portHandle);
            response.Code = writeReturn;
            if (writeReturn == 0)
            {
                response.Message = "“写EPC”指令返回=0x00（写EPC成功）。";
            }
            // 关闭UR5208的连接
            int closeReturn = UR5208Basic.CloseNetPort(portHandle);
            if (closeReturn != 0)
            {
                response.Code = openReturn;
                response.Message = "TCP/IP关闭端口错误";
            }
            return response;
        }

        /// <summary>
        /// 调用一次UR5208读写器读取一批RFID标签，并返回标签信息
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public List<string> UR5208Read(string ip, int port)
        {
            // 连接UR5208
            //string IPAddr = "192.168.1.190"; // RFID读写器的IP地址
            //int port = 6000; // RFID读写器的端口号

            byte fComAdr = Convert.ToByte("FF", 16); // $FF;
            int portHandle = 0; // 
            int openReturn = UR5208Basic.OpenNetPort(port, ip, ref fComAdr, ref portHandle);
            if (openReturn == 53) // 53表示已经打开端口
            {
                int closeReturnTemp = UR5208Basic.CloseNetPort(portHandle);
                if (closeReturnTemp != 0)
                {
                    throw new Exception("TCP/IP关闭错误");
                }
                openReturn = UR5208Basic.OpenNetPort(port, ip, ref fComAdr, ref portHandle);
            }
            if ((openReturn == 0x35) || (openReturn == 0x30))
            {
                throw new Exception("TCP/IP通讯错误");
            }
            //if ((portHandle != -1) && (openReturn != 0X35) && (openReturn != 0X30))
            //{
            //    throw new Exception("TCP/IP通讯错误");
            //}
            //if ((portHandle == -1) && (openReturn == 0x30))
            //{
            //    //MessageBox.Show("TCPIP 通讯错误", "信息");
            //    throw new Exception("TCP/IP 通讯错误");
            //}
            int i;
            int CardNum = 0;
            int Totallen = 0;
            int EPClen, m;
            byte[] EPC = new byte[5000];
            int CardIndex;
            string temps;
            string s, sEPC;
            byte AdrTID = 0;
            byte LenTID = 0;
            byte TIDFlag = 0;
            var list = new List<string>();
            int fCmdRet = UR5208Basic.Inventory_G2(ref fComAdr, AdrTID, LenTID, TIDFlag, EPC, ref Totallen, ref CardNum, portHandle);
            if ((fCmdRet == 1) | (fCmdRet == 2) | (fCmdRet == 3) | (fCmdRet == 4) | (fCmdRet == 0xFB))//代表已查找结束（目前实测1表示已读到，251表示未读到）
            {
                byte[] daw = new byte[Totallen];
                Array.Copy(EPC, daw, Totallen);
                temps = ByteArrayToHexString(daw);
                m = 0;

                if (CardNum != 0)
                {
                    for (CardIndex = 0; CardIndex < CardNum; CardIndex++)
                    {
                        EPClen = daw[m];
                        sEPC = temps.Substring(m * 2 + 2, EPClen * 2);
                        //s = (sEPC.Length / 2).ToString().PadLeft(2, '0');
                        m = m + EPClen + 1;
                        if (sEPC.Length != EPClen * 2)
                            continue;

                        if (!list.Contains(sEPC))
                        {
                            list.Add(sEPC);
                        }
                    }
                }
            }
            // 关闭UR5208的连接
            int closeReturn = UR5208Basic.CloseNetPort(portHandle);
            if (closeReturn != 0)
            {
                throw new Exception("TCP/IP关闭错误");
            }
            return list;
        }

        /// <summary>
        /// 调用一次UR5208读写器写入一张RFID标签
        /// </summary>
        /// <param name="ip">读写器IP地址</param>
        /// <param name="port">读写器端口（UR5208的端口是6000）</param>
        /// <param name="data">写入ECP区的数据（16进制数）</param>
        /// <returns>返回状态信息</returns>
        /// <exception cref="Exception">通信错误</exception>
        public ResponseDto UR5208Write(string ip, int port, string data)
        {
            var response = new ResponseDto();
            // 连接UR5208
            //string IPAddr = "192.168.1.190"; // RFID读写器的IP地址
            //int port = 6000; // RFID读写器的端口号

            byte fComAdr = Convert.ToByte("FF", 16); // $FF;
            int portHandle = 0; // 
            int openReturn = UR5208Basic.OpenNetPort(port, ip, ref fComAdr, ref portHandle);
            if (openReturn == 53) // 53表示已经打开端口
            {
                int closeReturnTemp = UR5208Basic.CloseNetPort(portHandle);
                if (closeReturnTemp != 0)
                {
                    response.Code = openReturn;
                    response.Message = "TCP/IP关闭端口错误";
                    return response;
                }
                openReturn = UR5208Basic.OpenNetPort(port, ip, ref fComAdr, ref portHandle);
            }
            if ((openReturn == 0x35) || (openReturn == 0x30))
            {
                response.Code = openReturn;
                response.Message = "TCP/IP通讯错误";
                return response;
            }
            //if ((portHandle != -1) && (openReturn != 0X35) && (openReturn != 0X30))
            //{
            //    throw new Exception("TCP/IP通讯错误");
            //}
            //if ((portHandle == -1) && (openReturn == 0x30))
            //{
            //    //MessageBox.Show("TCPIP 通讯错误", "信息");
            //    throw new Exception("TCP/IP 通讯错误");
            //}
            int errorCode = -1;
            //byte[] WriteEPC = new byte[100];
            byte WriteEPClen = Convert.ToByte(data.Length / 2);
            //byte ENum = Convert.ToByte(data.Length / 4);
            byte[] EPC = HexStringToByteArray(data);
            var fPassWord = HexStringToByteArray("00000000"); // 默认密码
            int fCmdRet = UR5208Basic.WriteEPC_G2(ref fComAdr, fPassWord, EPC, WriteEPClen, ref errorCode, portHandle);
            response.Code = fCmdRet;
            if (fCmdRet == 0)
            {
                response.Message = "“写EPC”指令返回=0x00（写EPC成功）。";
            }
            // 关闭UR5208的连接
            int closeReturn = UR5208Basic.CloseNetPort(portHandle);
            if (closeReturn != 0)
            {
                response.Code = openReturn;
                response.Message = "TCP/IP关闭端口错误";
            }
            return response;
        }

        private byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }

        private string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
            return sb.ToString().ToUpper();
        }
    }
}
